How does this apply to BizTalk Server solutions?
When
thinking about abstraction and information hiding in BizTalk Server,
I'd like to focus on how BizTalk functionality is exposed to the
outside world. Here I'll highlight two ways to respect the abstraction
principle in BizTalk Server.
First,
let's talk about how orchestrations are consumed by outside parties. In
truth, they are never directly exposed to a service consumer. It's
impossible to instantiate a BizTalk orchestration without going through
the adapter layer. So when we develop external service interfaces that
front orchestrations, we should be diligent and not reveal aspects of
our orchestration that the service consumer shouldn't know about. We
can accomplish this in part by always starting our projects in a
contract-driven manner by building the schema first, and then go about
building an orchestration. If we design in reverse, it is likely that
the orchestration's implementation logic seeps into the schema design.
For instance, let's say that my orchestration sends employee data to a
SQL Server database and also interacts with a web service exposed by a
TIBCO messaging server. If I built my orchestration first, and then
built up my schema along the way, I might be tempted to add fields to
my employee schema where I can store a TIBCO_Response and capture and store a SQL_Exception.
Then if I used the BizTalk WCF Service Publishing Wizard
to expose my orchestration as a service, I'd have an externally-facing
schema polluted with information about my technical implementation. My
service consumer should have no knowledge about what my orchestration
does to complete its task.
Another
critical way to show regard for the abstraction principle is by
thoughtfully considering how to expose downstream system interfaces to
upstream consumers. Let's say that you need to integrate with a Siebel
application and insert new customer contacts. The WCF LOB Adapter for
Siebel allows you to auto-generate the bits needed by a BizTalk
orchestration to consume the target Siebel operations. When exposing
that orchestration's port as a service interface, it would be a very
bad decision to assign the Siebel-generated schema as our instantiating
contract. There are two reasons I would avoid doing this at all costs:
This
tightly couples our service consumer to an implementation decision.
Ignoring the fact that LOB system generated schemas are typically
verbose and hard to digest, our service consumer should neither care
nor know about how the orchestration processes the new customer. By
sharing LOB system schemas as orchestration schemas, you've lost any
opportunity to provide an abstract interface.
A
service typically offers a simplified interface to complex downstream
activities. What if Siebel required three distinct operations to be
called in order to insert a new customer? Should we expose three
services from BizTalk Server and expect the service client to
coordinate these calls? Absolutely not. As we discussed earlier,
slapping SOAP interfaces onto existing APIs does not make an
application service-oriented. Instead, we want to look for
opportunities to offer services that aggregate downstream actions into
a single coarse-grained exterior interface.
A
good strategy for interfacing with LOB systems is to identify a single
canonical schema that encapsulates all the data necessary to populate
the downstream LOB systems regardless of how many individual LOB
operations are needed. This strategy has two benefits. First, you
obtain significant control over the structure of your service contract
instead of being subjected to a data structure generated by an adapter.
Secondly, we achieve a much more flexible interface that is no longer
dependent on a particular implementation. What if the downstream LOB
system changes its interface or the target LOB system changes
completely? In theory, the service consumer can remain blissfully
unaware of these circumstances as their interface is cleanly separated
from the final data repository used by the service.
Interoperable
SOA-compatible
services need to support cross-platform invocation and the service
itself will often access a heterogeneous set of data and functions.
Interoperability is all about making diverse systems work together and
it is a critical component of a long-term SOA.
Similar
to all of the core SOA principles, service interoperability needs to be
designed early in the project lifecycle instead of being an
afterthought addressed only moments before production deployment. Now
interoperability doesn't mean that the service has to accommodate a mix
of runtime host environments. A service that fails to run in both
Microsoft IIS and BEA WebLogic hosting platforms doesn't mean that I've
written a closed, poorly-designed service. When we talk about
interoperability, we are concentrating on how a wide variety of
disparate clients
can access a single service. Is the fact that my service was written in
.NET 3.5 and hosted by IIS 7.0 completely transparent to my Java, .NET,
and Ruby users? If your service was written well, then the answer to
that question should be "yes".
As
for service implementation, you ideally want to empower your service to
yank data from any available source. To do so, the service needs a
means to access diverse sets of resources that may not natively expose
simple interfaces. This is where a service/integration bus can truly
shine. Some applications just won't naturally play nice with each
other. But a service bus with built-in adapter technology can bridge
those gaps and enable unfriendly systems to share and consume data from
the outside. For example, the BizTalk Adapters for Host Systems produce
no-code integration solutions for IBM mainframe technology. I can write
a snazzy WCF service that chews on and returns data that dwells in VSAM
host file and the service client remains blissfully unaware. The
adapters in BizTalk Server enable us to build rich services that
penetrate existing non-service-oriented applications and seamlessly
weave their data into the service result.
So
how do you achieve interoperability in your service environment? First
and foremost, you want to adhere to the standard entities that
typically describe services and their behavior. The "big four"
technologies to keep in mind are WSDL (for service contract
description), XSD (for message structure definition), SOAP (the
protocol for sending service messages) and UDDI (for service
registration and discovery). All of these technologies are considered
"cross-platform" and are readily supported by both major and minor
software vendors. Do you need to use each of these technologies in
order to provide an interoperable service? Definitely not. Some find
WSDLs to be obtuse and unnecessary and still others find XSD to be a
lousy way to organize data. However, given BizTalk's embrace of these
artifact types, I'll work within these confines.
I'd
be remiss if I didn't mention that service interoperability is also
quite possible through services written in a RESTful manner. That is,
services that don't use the more verbose SOAP interface and instead
rally around HTTP URI significance, distinct "resources", transferring
resource representations, and the well-defined HTTP verbs. RESTful
services typically offer a looser concept of a "message contract" and
don't provide a standard way to share the representations that the
service expects or returns. Although WCF now has full support for
RESTful services, the BizTalk WCF adapter does not readily expose or
consume such endpoints. Note that I won't spend much time analyzing
RESTful services in this book.
When
building a service for interoperability, what do you need to consider?
From my perspective, interoperability design comes in at four major
points:
Endpoint choice:
If you truly intend for your service to be available to the widest
range of consumers, then you need to pick an endpoint that is
accessible to the masses. Simply put, pick a protocol like HTTP that
everyone can support. Now, there's no shame in exposing WCF's netTcpBinding endpoint for targeted consumers, but be aware that you've instantly settled on a .NET-to-.NET only solution.
Data structure:
Properly selecting friendly XML data types and node behaviors is a
vital part of building an interoperable service message. How are
decimals handled? What's the precision of a floating point number for
.NET versus. Java? For intricate calculations, those answers have a
significant impact on the accuracy of data used by the service. Also
don't forget about date/time handling either, as XSD has a very rigid datetime data type (CCYY-MM-DDThh:mm:ss), but either source or destination systems may enforce an alternate format.
Security scheme:
Cross-platform security can be a challenge, but without it, one cannot
truly put forward an interoperable service. Even with the WS-Security
standard itself, you are bound to come across existing service clients
who support different versions or flavors of these standards, thus
making pure interoperability impossible.
Transaction support:
The naturally stateless nature of most services makes the idea of a
two-phase commit problematic to implement. When either exposing a
service that must accept a transaction, or when the internal functions
of a service require the assistance of a transaction, you want to lean
heavily on standard mechanisms that can ensure the widest range of
compatibility across platforms and technologies.
Completely non-technical interoperability example
For
me, a true test of a quality ethnic restaurant is if the people working
there are of the same ethnicity that the restaurant touts as its
speciality. However, what if the chef doesn't speak the same language
as the waiter? In this case, they rely on multiple means of
interoperability. First, they can use a taxonomy consisting of letter
codes or numbers to represent the meals requested by patrons. Secondly,
they can employ a single translator who proxies communication between
the personnel who don't natively speak the same language.